package cn.coderdream.anim;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.text.TextUtils;
import android.view.View;
import android.view.animation.Interpolator;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 作者: 孟鹏
 * 时间: 2020/5/17 - 23:31
 * 作用: 动画工具类
 */
public class MAnim {
    private static MAnim mMAnim;
    private static List<Map<String, Object>> mList = null;
    private final String AnimHelper_Anim = "ANIM";
    private final String AnimHelper_Listener = "LISTENER";

    public static MAnim getInstance() {
        if (mMAnim == null) {
            mMAnim = new MAnim();
        }
        if (mList == null) {
            mList = new ArrayList<>();
        }
        mList.clear();
        return mMAnim;
    }

    public class with {
        private View mView;
        private boolean isLoop;

        public with(View mView) {
            this.mView = mView;
        }

        public with(View mView, boolean isLoop) {
            this.mView = mView;
            this.isLoop = isLoop;
        }

        public with alpha(long duration, float... values) {
            return alpha(duration, null, values);
        }

        public with alpha(long duration, Interpolator mInterpolator, float... values) {
            return alpha(0, duration, mInterpolator, values);
        }

        public with alpha(long waitTime, long duration, float... values) {
            return alpha(waitTime, duration, null, values);
        }

        public with alpha(long waitTime, long duration, Interpolator mInterpolator, float... values) {
            ObjectAnimator alpha = ObjectAnimator.ofFloat(mView, "alpha", values);
            alpha.setDuration(duration);
            if (isLoop) {
                alpha.setRepeatCount(ValueAnimator.INFINITE);
            }
            if (mInterpolator != null) {
                alpha.setInterpolator(mInterpolator);
            }
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setStartDelay(waitTime);
            animatorSet.play(alpha);
            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Anim);
            map.put("anim", animatorSet);
            mList.add(map);
            return this;
        }

        public with scaleX(long duration, float... values) {
            return scaleX(duration, null, values);
        }

        public with scaleX(long duration, Interpolator mInterpolator, float... values) {
            return scaleX(0, duration, mInterpolator, values);
        }

        public with scaleX(long waitTime, long duration, float... values) {
            return scaleX(0, duration, null, values);
        }

        public with scaleX(long waitTime, long duration, Interpolator mInterpolator, float... values) {
            ObjectAnimator scaleX = ObjectAnimator.ofFloat(mView, "scaleX", values);
            scaleX.setDuration(duration);
            if (mInterpolator != null) {
                scaleX.setInterpolator(mInterpolator);
            }
            if (isLoop) {
                scaleX.setRepeatCount(ValueAnimator.INFINITE);
            }
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setStartDelay(waitTime);
            animatorSet.playTogether(scaleX);
            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Anim);
            map.put("anim", animatorSet);
            mList.add(map);
            return this;
        }

        public with scaleY(long duration, float... values) {
            return scaleY(0, duration, null, values);
        }

        public with scaleY(long duration, Interpolator mInterpolator, float... values) {
            return scaleY(0, duration, mInterpolator, values);
        }

        public with scaleY(long waitTime, long duration, float... values) {
            return scaleY(waitTime, duration, null, values);
        }

        public with scaleY(long waitTime, long duration, Interpolator mInterpolator, float... values) {
            ObjectAnimator scaleY = ObjectAnimator.ofFloat(mView, "scaleY", values);
            scaleY.setDuration(duration);
            if (isLoop) {
                scaleY.setRepeatCount(ValueAnimator.INFINITE);
            }
            if (mInterpolator != null) {
                scaleY.setInterpolator(mInterpolator);
            }
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setStartDelay(waitTime);
            animatorSet.playTogether(scaleY);

            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Anim);
            map.put("anim", animatorSet);
            mList.add(map);
            return this;
        }

        public with scaleXY(long duration, float[] xValues, float[] yValues) {
            return scaleXY(duration, null, xValues, yValues);
        }

        public with scaleXY(long duration, Interpolator interpolator, float[] xValues, float[] yValues) {
            return scaleXY(0, duration, interpolator, xValues, yValues);
        }

        public with scaleXY(long waitTime, long duration, float[] xValues, float[] yValues) {
            return scaleXY(waitTime, duration, null, xValues, yValues);
        }

        public with scaleXY(long waitTime, long duration, Interpolator interpolator, float[] xValues, float[] yValues) {
            ObjectAnimator scaleX = ObjectAnimator.ofFloat(mView, "scaleX", xValues);
            ObjectAnimator scaleY = ObjectAnimator.ofFloat(mView, "scaleY", yValues);
            scaleX.setDuration(duration);
            scaleY.setDuration(duration);

            if (isLoop) {
                scaleX.setRepeatCount(ValueAnimator.INFINITE);
                scaleY.setRepeatCount(ValueAnimator.INFINITE);
            }

            if (interpolator != null) {
                scaleX.setInterpolator(interpolator);
                scaleY.setInterpolator(interpolator);
            }

            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setStartDelay(waitTime);
            animatorSet.playTogether(scaleX, scaleY);

            animatorSet.setInterpolator(interpolator);

            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Anim);
            map.put("anim", animatorSet);
            mList.add(map);
            return this;
        }

        public with translationX(long duration, float... values) {
            return translationX(duration, null, values);
        }

        public with translationX(long duration, Interpolator interpolator, float... values) {
            return translationX(0, duration, interpolator, values);
        }

        public with translationX(long waitTime, long duration, float... values) {
            return translationX(waitTime, duration, null, values);
        }

        public with translationX(long waitTime, long duration, Interpolator interpolator, float... values) {
            ObjectAnimator translationX = ObjectAnimator.ofFloat(mView, "translationX", values);
            translationX.setDuration(duration);
            if (interpolator != null) {
                translationX.setInterpolator(interpolator);
            }
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setStartDelay(waitTime);
            animatorSet.play(translationX);
            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Anim);
            map.put("anim", animatorSet);
            mList.add(map);
            return this;
        }

        public with translationY(long duration, float... values) {
            return translationY(duration, null, values);
        }

        public with translationY(long duration, Interpolator interpolator, float... values) {
            return translationY(0, duration, interpolator, values);
        }

        public with translationY(long waitTime, long duration, float... values) {
            return translationY(waitTime, duration, null, values);
        }

        public with translationY(long waitTime, long duration, Interpolator interpolator, float... values) {
            ObjectAnimator translationY = ObjectAnimator.ofFloat(mView, "translationY", values);
            translationY.setDuration(duration);
            if (interpolator != null) {
                translationY.setInterpolator(interpolator);
            }
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setStartDelay(waitTime);
            animatorSet.play(translationY);
            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Anim);
            map.put("anim", animatorSet);
            mList.add(map);
            return this;
        }

        public with translationXY(long duration, float[] xValues, float[] yValues) {
            return translationXY(duration, null, xValues, yValues);
        }

        public with translationXY(long duration, Interpolator mInterpolator, float[] xValues, float[] yValues) {
            return translationXY(0, duration, mInterpolator, xValues, yValues);
        }

        public with translationXY(long waitTime, long duration, float[] xValues, float[] yValues) {
            return translationXY(waitTime, duration, null, xValues, yValues);
        }

        public with translationXY(long waitTime, long duration, Interpolator mInterpolator, float[] xValues, float[] yValues) {
            ObjectAnimator translationX = ObjectAnimator.ofFloat(mView, "translationX", xValues);
            ObjectAnimator translationY = ObjectAnimator.ofFloat(mView, "translationY", yValues);
            translationX.setDuration(duration);
            translationY.setDuration(duration);

            if (isLoop) {
                translationX.setRepeatCount(ValueAnimator.INFINITE);
                translationY.setRepeatCount(ValueAnimator.INFINITE);
            }

            if (mInterpolator != null) {
                translationX.setInterpolator(mInterpolator);
                translationY.setInterpolator(mInterpolator);
            }

            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setStartDelay(waitTime);
            animatorSet.playTogether(translationX, translationY);
            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Anim);
            map.put("anim", animatorSet);
            mList.add(map);
            return this;
        }

        public with translation(long duration, float[] xValues, float[] yValues) {
            return translation(duration, null, xValues, yValues);
        }

        public with translation(long duration, Interpolator interpolator, float[] xValues, float[] yValues) {
            return translation(0, duration, interpolator, xValues, yValues);
        }

        public with translation(long waitTime, long duration, float[] xValues, float[] yValues) {
            return translation(waitTime, duration, null, xValues, yValues);
        }

        public with translation(long waitTime, long duration, Interpolator interpolator, float[] xValues, float[] yValues) {
            ObjectAnimator translationX = ObjectAnimator.ofFloat(mView, "translationX", xValues);
            ObjectAnimator translationY = ObjectAnimator.ofFloat(mView, "translationY", yValues);
            translationX.setDuration(duration);
            translationY.setDuration(duration);
            if (interpolator != null) {
                translationX.setInterpolator(interpolator);
                translationY.setInterpolator(interpolator);
            }
            if (isLoop) {
                translationX.setRepeatCount(ValueAnimator.INFINITE);
                translationY.setRepeatCount(ValueAnimator.INFINITE);
            }
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setStartDelay(waitTime);
            animatorSet.playTogether(translationX, translationY);

            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Anim);
            map.put("anim", animatorSet);
            mList.add(map);
            return this;
        }

        public with rotationX(long duration, float... values) {
            return rotationX(duration, null, values);
        }

        public with rotationX(long duration, Interpolator mInterpolator, float... values) {
            return rotationX(0, duration, mInterpolator, values);
        }

        public with rotationX(long waitTime, long duration, float... values) {
            return rotationX(waitTime, duration, null, values);
        }

        public with rotationX(long waitTime, long duration, Interpolator mInterpolator, float... values) {
            ObjectAnimator rotationX = ObjectAnimator.ofFloat(mView, "rotationX", values);
            rotationX.setDuration(duration);
            if (isLoop) {
                rotationX.setRepeatCount(ValueAnimator.INFINITE);
            }
            if (mInterpolator != null) {
                rotationX.setInterpolator(mInterpolator);
            }
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setStartDelay(waitTime);
            animatorSet.play(rotationX);
            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Anim);
            map.put("anim", animatorSet);
            mList.add(map);
            return this;
        }

        public with rotationY(long duration, float... values) {
            return rotationY(duration, values);
        }

        public with rotationY(long duration, Interpolator mInterpolator, float... values) {
            return rotationY(0, duration, mInterpolator, values);
        }

        public with rotationY(long waitTime, long duration, float... values) {
            return rotationY(waitTime, duration, null, values);
        }

        public with rotationY(long waitTime, long duration, Interpolator mInterpolator, float... values) {
            ObjectAnimator rotationY = ObjectAnimator.ofFloat(mView, "rotationY", values);
            rotationY.setDuration(duration);
            if (isLoop) {
                rotationY.setRepeatCount(ValueAnimator.INFINITE);
            }
            if (mInterpolator != null) {
                rotationY.setInterpolator(mInterpolator);
            }
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setStartDelay(waitTime);
            animatorSet.play(rotationY);
            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Anim);
            map.put("anim", animatorSet);
            mList.add(map);
            return this;
        }

        public with rotationXY(long duration, float[] xValues, float[] yValues) {
            return rotationXY(0, duration, xValues, yValues);
        }

        public with rotationXY(long duration, Interpolator mInterpolator, float[] xValues, float[] yValues) {
            return rotationXY(0, duration, mInterpolator, xValues, yValues);
        }

        public with rotationXY(long waitTime, long duration, float[] xValues, float[] yValues) {
            return rotationXY(waitTime, duration, null, xValues, yValues);
        }

        public with rotationXY(long waitTime, long duration, Interpolator mInterpolator, float[] xValues, float[] yValues) {
            ObjectAnimator rotationX = ObjectAnimator.ofFloat(mView, "rotationX", xValues);
            ObjectAnimator rotationY = ObjectAnimator.ofFloat(mView, "rotationY", yValues);
            if (isLoop) {
                rotationX.setRepeatCount(ValueAnimator.INFINITE);
                rotationY.setRepeatCount(ValueAnimator.INFINITE);
            }
            if (mInterpolator != null) {
                rotationX.setInterpolator(mInterpolator);
                rotationY.setInterpolator(mInterpolator);
            }
            rotationX.setDuration(duration);
            rotationY.setDuration(duration);
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setStartDelay(waitTime);
            animatorSet.playTogether(rotationX, rotationY);
            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Anim);
            map.put("anim", animatorSet);
            mList.add(map);
            return this;
        }

        public with rotation(long duration, float... values) {
            return rotation(duration, null, values);
        }

        public with rotation(long duration, Interpolator mInterpolator, float... values) {
            return rotation(0, duration, mInterpolator, values);
        }

        public with rotation(long waitTIme, long duration, float... values) {
            return rotation(waitTIme, duration, null, values);
        }

        public with rotation(long waitTime, long duration, Interpolator mInterpolator, float... values) {
            ObjectAnimator rotation = ObjectAnimator.ofFloat(mView, "rotation", values);
            rotation.setDuration(duration);
            if (isLoop) {
                rotation.setRepeatCount(ValueAnimator.INFINITE);
            }
            if (mInterpolator != null) {
                rotation.setInterpolator(mInterpolator);
            }
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setStartDelay(waitTime);
            animatorSet.play(rotation);
            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Anim);
            map.put("anim", animatorSet);
            mList.add(map);
            return this;
        }

        public with call(AnimListener mAnimListener) {
            Map<String, Object> map = new HashMap<>();
            map.put("type", AnimHelper_Listener);
            map.put("listener", mAnimListener);
            mList.add(map);
            return this;
        }

        public void start() {
            if (mList != null && mList.size() > 0) {

                Map<String, Object> objectMap = mList.get(0);
                String type = (String) objectMap.get("type");
                if (!TextUtils.isEmpty(type) && type.equals(AnimHelper_Anim)) {//执行动画
                    AnimatorSet animatorSet = (AnimatorSet) objectMap.get("anim");
                    if (animatorSet != null) {
                        animatorSet.start();
                        animatorSet.addListener(new Animator.AnimatorListener() {
                            @Override
                            public void onAnimationStart(Animator animation) {

                            }

                            @Override
                            public void onAnimationEnd(Animator animation) {
                                if (mList.size() > 0) {
                                    mList.remove(0);
                                }
                                start();
                            }

                            @Override
                            public void onAnimationCancel(Animator animation) {

                            }

                            @Override
                            public void onAnimationRepeat(Animator animation) {

                            }
                        });
                    }
                } else if (!TextUtils.isEmpty(type) && type.equals(AnimHelper_Listener)) {//执行监听事件
                    AnimListener listener = (AnimListener) objectMap.get("listener");
                    if (listener != null) {
                        listener.onAnimEnd();
                    }
                    if (mList.size() > 0) {
                        mList.remove(0);
                    }
                    start();
                }
            }
        }
    }
}
